home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
TextCmd.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-06
|
14KB
|
600 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "TextCmd.h"
#include "Class.h"
#include "TextView.h"
#include "CmdNo.h"
#include "StyledText.h"
#include "RunArray.h"
#include "Math.h"
//---- range functions ---------------------------------------------------------
void CharacterRange(Text*, int at, int *start, int *end)
{
*start= *end= at;
}
void WordRange(Text *t, int at, int *start, int *end)
{
t->GetWordRange(at, start, end);
}
void ParagraphRange(Text *t, int at, int *start, int *end)
{
t->GetParaRange(at, start, end);
}
//---- RangeSelector -----------------------------------------------------------
RangeSelector::RangeSelector(class TextView *t, TextRangeFP f)
{
tv= t;
range= f;
}
Command *RangeSelector::TrackMouse(TrackPhase tp, Point, Point np, Point)
{
SelPoint nextp;
int start, end;
np= np-tv->GetInnerOrigin();
switch (tp) {
case eTrackPress:
tv->DoneTyping();
tv->inTextSelector= TRUE;
tv->PointToPoint(np, &nextp.viewp, &nextp.line, &nextp.ch);
Range(tv->GetText(), nextp.ch, &start, &end);
DoPress(nextp, start, end);
break;
case eTrackMove:
tv->PointToPoint(np, &nextp.viewp, &nextp.line, &nextp.ch);
Range(tv->GetText(), nextp.ch, &start, &end);
DoMove(nextp, start, end);
break;
case eTrackRelease:
tv->inTextSelector= FALSE;
if ((tv->start.line == tv->end.line) && tv->Caret())
tv->InvalidateSelection();
tv->NormSelection();
return gNoChanges;
}
return this;
}
void RangeSelector::Range(Text *t, int at, int *from, int *to)
{
range(t, at, from, to);
*to= Math::Min(t->End(), *to);
}
void RangeSelector::DoPress(SelPoint, int s, int e)
{
tv->PrivSetSelection(s, e, FALSE);
startp= tv->start;
endp= tv->end;
}
void RangeSelector::DoMove(SelPoint nextp, int s, int e)
{
if (nextp.ch <= startp.ch) {
tv->CharToPoint (nextp.ch= s, &nextp.line, &nextp.viewp);
if (!nextp.IsEqual(tv->start)) {
tv->InvalidateRange(nextp.line, nextp.viewp, tv->start.line, tv->start.viewp);
tv->start= nextp;
}
else if (tv->end.ch > endp.ch && !endp.IsEqual(tv->end)) {
tv->InvalidateRange(endp.line, endp.viewp, tv->end.line, tv->end.viewp);
tv->end= endp;
}
} else {
tv->CharToPoint(nextp.ch= e, &nextp.line, &nextp.viewp);
if (!nextp.IsEqual(tv->end)) {
tv->InvalidateRange(tv->end.line, tv->end.viewp, nextp.line, nextp.viewp);
tv->end= nextp;
}
else if (tv->start.ch < startp.ch && !startp.IsEqual(tv->start)) {
tv->InvalidateRange(tv->start.line, tv->start.viewp, startp.line, startp.viewp);
tv->start= startp;
}
}
}
//---- ExtendRangeSelector ----------------------------------------------------
ExtendRangeSelector::ExtendRangeSelector(TextView *tv, TextRangeFP rf)
: RangeSelector(tv, rf)
{
swap= FALSE;
}
void ExtendRangeSelector::DoPress(SelPoint nextp, int s, int e)
{
startp.ch= s;
endp.ch= e;
if (nextp.ch <= tv->start.ch) { // extend at start
tv->CharToPoint(startp.ch, &startp.line, &startp.viewp);
tv->InvalidateRange(startp.line, startp.viewp, tv->start.line, tv->start.viewp);
tv->start= startp;
swap= TRUE;
} else { // extend at end
tv->CharToPoint(endp.ch, &endp.line, &endp.viewp);
tv->InvalidateRange(tv->end.line, tv->end.viewp, endp.line, endp.viewp);
tv->end= endp;
}
startp= nextp;
}
void ExtendRangeSelector::DoMove(SelPoint nextp, int s, int e)
{
if (swap) {
swap= FALSE;
SwapSelPoints(tv->start, tv->end);
}
if (nextp.ch < startp.ch)
tv->CharToPoint(nextp.ch= s, &nextp.line, &nextp.viewp);
else
tv->CharToPoint(nextp.ch= e, &nextp.line, &nextp.viewp);
if (!nextp.IsEqual(tv->end)) {
tv->InvalidateRange(nextp.line, nextp.viewp, tv->end.line, tv->end.viewp);
tv->end= nextp;
}
}
//---- QuickPasteSelector ------------------------------------------------------
QuickPasteSelector::QuickPasteSelector(class TextView *tv, int f, int t)
: RangeSelector(tv)
{
from= f;
to= t;
}
Command *QuickPasteSelector::TrackMouse(TrackPhase tp, Point ap, Point pp, Point np)
{
Command *cmd= RangeSelector::TrackMouse(tp, ap, pp, np);
if (tp == eTrackRelease) {
if (tv->Caret()) {
tv->SetSelection(from, to);
return gNoChanges;
}
Text *t= tv->SelectionAsText();
tv->SetSelection(from, to);
return new PasteCommand(tv, t);
}
return cmd;
}
//---- DragAndDropSelector ---------------------------------------------------
GrCursor DragAndDropSelector::oldcursor;
DragAndDropSelector::DragAndDropSelector(class TextView *tvp, int s, int e, bool p)
{
dst= from= s;
to= e;
tv= tvp;
moved= FALSE;
paste= p;
t= tvp->GetText();
}
Command *DragAndDropSelector::TrackMouse(TrackPhase tp, Point ap, Point, Point np)
{
delta= np-ap;
switch (tp) {
case eTrackPress:
oldcursor= GrGetCursor();
break;
case eTrackMove:
if (Math::Abs(delta.x) > 4 || Math::Abs(delta.y) > 4) {
GrSetCursor(eCrsMoveHand);
moved= TRUE;
}
break;
case eTrackRelease:
GrSetCursor(oldcursor);
tv->SetSelection(dst, dst, TRUE);
if (moved && !(dst >= from && dst < to)) {
Text *txtsrc= t->Save(from, to);
tv->SetSelection(dst, dst, TRUE);
if (paste || tv->DeleteRequest(from, to) == FALSE)
return new PasteCommand(tv, txtsrc);
return new MoveTextCommand(tv, from, to, dst);
}
return gNoChanges;
}
return this;
}
void DragAndDropSelector::TrackFeedback(Point, Point np, bool)
{
Point p;
int line;
np= np-tv->GetInnerOrigin();
tv->PointToPoint(np, &p, &line, &dst);
if (dst < from || dst >= to)
DrawCaretFeedback(dst);
}
void DragAndDropSelector::DrawCaretFeedback(int at)
{
int l;
Point p;
tv->CharToPoint(at, &l, &p);
p+= tv->GetInnerOrigin();
int bh= tv->BaseHeight(l);
GrSetInk(gInkXor);
GrMoveto(p);
GrLineto(Point(p.x, p.y+bh));
}
//----- TextCommand Methods ----------------------------------------------------
NewAbstractMetaImpl(TextCommand, Command, (TP(tv), TP(oldText), T(oldStart), T(oldEnd)));
TextCommand::TextCommand (TextView *t, int cmdNo, char *cmdName, bool save)
: Command(cmdNo, cmdName)
{
tv= t;
tv->GetSelection(&oldStart, &oldEnd);
oldText= (Text*)tv->GetText()->New();
if (save && oldStart != oldEnd) // save old text
tv->Copy(oldText);
}
TextCommand::~TextCommand ()
{
SafeDelete(oldText);
}
void TextCommand::RestoreSelection ()
{
tv->SetSelection(oldStart, oldEnd, FALSE);
}
void TextCommand::RedoIt()
{
RestoreSelection();
DoIt();
tv->RevealSelection();
}
//----- CutCopyCommand Methods -------------------------------------------------
NewMetaImpl0(CutCopyCommand, TextCommand);
CutCopyCommand::CutCopyCommand(TextView *t, int cmdNo, char *cmdName)
: TextCommand(t, cmdNo, 0, cmdNo != cCOPY)
{
if (cmdName == 0) {
if (cmdNo == cCUT)
cmdName= "Cut Text";
else if (cmdNo == cCOPY)
cmdName= "Copy Text";
}
SetName(cmdName);
if (cmdNo == cCOPY)
SetType(eCmdTypeNoChange);
}
void CutCopyCommand::DoIt()
{
if (GetId() == cCOPY)
return;
tv->Cut();
tv->RevealSelection();
}
void CutCopyCommand::UndoIt()
{
Text *t= tv->GetText();
if (GetId() == cCUT) {
tv->SetSelection(oldStart, oldStart, FALSE);
if (oldText->End() != 0)
tv->Paste(oldText);
RestoreSelection();
tv->RevealSelection();
}
}
//----- Paste Command Methods --------------------------------------------------
NewMetaImpl(PasteCommand, TextCommand, (TP(pastetext), T(newStart), T(newEnd)));
PasteCommand::PasteCommand(TextView *t, Text *pt, int cmdNo, char *cmdName)
: TextCommand(t, cmdNo, cmdName ? cmdName : "Paste Text")
{
pastetext= pt;
}
PasteCommand::~PasteCommand()
{
SafeDelete(pastetext);
}
void PasteCommand::DoIt()
{
tv->Paste(pastetext);
tv->GetSelection(&newStart, &newEnd);
tv->RevealSelection();
}
void PasteCommand::UndoIt()
{
tv->SetSelection(oldStart, newEnd, FALSE);
tv->Cut();
if (oldText->End() != 0)
tv->Paste(oldText);
RestoreSelection();
tv->RevealSelection();
}
//---- MoveTextCommand -------------------------------------------------------
MoveTextCommand::MoveTextCommand(TextView *tview, int f, int t, int d)
: Command(cPASTE, "Move Text")
{
tv= tview;
from= f;
to= t;
dst= d;
mt= 0;
}
MoveTextCommand::~MoveTextCommand()
{
SafeDelete(mt);
}
void MoveTextCommand::DoIt()
{
int nd= dst;
if (dst > from)
nd= nd-(to-from);
if (!mt)
mt= tv->GetText()->Save(from, to);
tv->SetSelection(from, to, FALSE);
tv->Cut();
tv->SetSelection(nd, nd, FALSE);
tv->Paste(mt);
tv->SetSelection(nd, nd+to-from, FALSE);
tv->RevealSelection();
}
void MoveTextCommand::UndoIt()
{
int nd= dst;
if (dst > from)
nd= nd-(to-from);
tv->SetSelection(nd, nd+to-from, FALSE);
tv->Cut();
tv->SetSelection(from, from, FALSE);
tv->Paste(mt);
tv->SetSelection(from, to, FALSE);
tv->RevealSelection();
}
//----- TypeInCommand Command Methods ------------------------------------------
NewMetaImpl(TypingCommand, TextCommand,
(TP(backspaceBuf), TP(newText), T(newStart)));
TypingCommand::TypingCommand(TextView *t, int cmdNo, char *cmdName)
: TextCommand(t, cmdNo, cmdName)
{
Text *txt= tv->GetText();
backspaceBuf= (Text*) txt->New();
newText= (Text*) txt->New();
newStart= oldStart;
}
TypingCommand::~TypingCommand()
{
tv->TypingDeleted(this);
SafeDelete(backspaceBuf);
SafeDelete(newText);
}
void TypingCommand::UndoIt()
{
Text *t= tv->GetText();
int firstNewChar;
firstNewChar= Math::Min(oldStart - backspaceBuf->End(), oldStart);
if (firstNewChar != newStart) { // save new text
t->Copy(newText, firstNewChar, newStart);
tv->SetSelection(firstNewChar, newStart, TRUE);
tv->Cut(); // remove new text
} else
tv->SetSelection(firstNewChar, newStart, TRUE);
if (backspaceBuf->End() != 0)
tv->Paste(backspaceBuf); // insert saved text
if (oldText->End() != 0)
tv->Paste(oldText);
RestoreSelection();
tv->RevealSelection();
}
void TypingCommand::RedoIt()
{
RestoreSelection();
tv->Cut();
if (backspaceBuf->End() != 0) {
tv->SetSelection(oldStart - backspaceBuf->End(), oldStart, FALSE);
tv->Cut();
}
if (newText->End() != 0)
tv->Paste(newText);
tv->RevealSelection();
}
void TypingCommand::AddChar(int n)
{
newStart+= n;
}
void TypingCommand::DelChar()
{
Text *t= tv->GetText();
if (newStart > 0)
newStart--;
if (newStart < oldStart)
if (oldStart - newStart > backspaceBuf->End()) { // char already saved??
backspaceBuf->ReplaceRange(0, 0, t, newStart, newStart+1);
}
}
//---- class CharStyleCommand -------------------------------------------------------
NewMetaImpl(CharStyleCommand, TextCommand, (TP(newStyles), TP(oldStyles), TP(tvp), TE(mode)));
CharStyleCommand::CharStyleCommand(TextView *t, int cmdNo, char *cmdName,
TxtCharProp m, const CharStyleSpec &ns)
: TextCommand(t, cmdNo, cmdName, FALSE)
{
st= Guard(t->GetText(), StyledText);
newStyles= oldStyles= 0;
tvp= t;
style= ns;
mode= m;
}
CharStyleCommand::~CharStyleCommand()
{
SafeDelete(oldStyles);
SafeDelete(newStyles);
}
void CharStyleCommand::DoIt()
{
int from, to;
tvp->GetSelection(&from, &to);
if (tvp->Caret())
st->SetCharStyle(mode, from, to, style);
else {
if (oldStyles == 0)
oldStyles= new RunArray;
st->GetCharStyles()->Copy(oldStyles, from, to);
st->SetCharStyle(mode, from, to, style);
}
tvp->RevealSelection();
}
void CharStyleCommand::UndoIt()
{
if (oldStart == oldEnd)
st->ResetCurrentCharStyle();
else {
if (newStyles == 0) {
newStyles= new RunArray;
st->GetCharStyles()->Copy(newStyles, oldStart, oldEnd);
}
st->ReplaceCharStyles(oldStyles, oldStart, oldEnd);
}
RestoreSelection();
tvp->RevealSelection();
}
void CharStyleCommand::RedoIt()
{
if (oldStart == oldEnd)
st->SetCharStyle(mode, oldStart, oldEnd, style);
else
st->ReplaceCharStyles(newStyles, oldStart, oldEnd);
RestoreSelection();
tvp->RevealSelection();
}
//---- class ParaStyleCommand -------------------------------------------------------
NewMetaImpl(ParaStyleCommand, TextCommand, (TP(newStyles), TP(oldStyles), TP(tvp)));
ParaStyleCommand::ParaStyleCommand(
TextView *t, int cmdNo, char *cmdName, TxtParaProp p, const ParaDesc &newStyle
): TextCommand(t, cmdNo, cmdName, FALSE)
{
st= Guard(t->GetText(), StyledText);
newStyles= oldStyles= 0;
tvp= t;
mode= p;
style= newStyle;
notify= 0;
}
ParaStyleCommand::~ParaStyleCommand()
{
SafeDelete(oldStyles);
SafeDelete(newStyles);
if (notify)
notify->Control(cIdNone, cPartCommandDone, this);
}
void ParaStyleCommand::DoIt()
{
int from, to, dd;
tvp->GetSelection(&from, &to);
st->GetParaRange(from, &oldStart, &dd);
if (to == from)
oldEnd= dd;
else if (st->IsPara((*st)[to-1]))
oldEnd= to;
else
st->GetParaRange(to, &dd, &oldEnd);
if (oldStyles == 0) {
oldStyles= new RunArray;
st->GetParaStyles()->Copy(oldStyles, oldStart, oldEnd);
}
st->SetParaStyle(mode, oldStart, oldEnd, style);
tvp->RevealSelection();
}
void ParaStyleCommand::UndoIt()
{
if (newStyles == 0) {
newStyles= new RunArray;
st->GetParaStyles()->Copy(newStyles, oldStart, oldEnd);
}
st->ReplaceParaStyles(oldStyles, oldStart, oldEnd);
RestoreSelection();
tvp->RevealSelection();
}
void ParaStyleCommand::RedoIt()
{
st->ReplaceParaStyles(newStyles, oldStart, oldEnd);
RestoreSelection();
tvp->RevealSelection();
}
void ParaStyleCommand::Apply(TxtParaProp p, const ParaDesc &newStyle)
{
mode= p;
style= newStyle;
}
void ParaStyleCommand::NotifyWhenDone(EvtHandler *evt)
{
notify= evt;
}
TxtParaProp ParaStyleCommand::GetNewStyle(ParaDesc &newStyle)
{
newStyle= style;
return mode;
}